/*
 * Funny Language - a free style programming language.
 * Copyright (C) 2015 by fanguangping (fanguangping@163.com)
 * parser.c
 */

#include <string.h>
#include <ctype.h>
#include "parser.h"
#include "../base/utils.h"

static int is_symbol(String token) {
	if (strcmp(PAREN_L_STR, token) == 0 || strcmp(PAREN_R_STR, token) == 0) {
		return FALSE;
	} else {
		return TRUE;
	}
}

Statement *parse_statement(String token, Input *input) {
	Statement *root = NULL, *s = NULL;
	String the_next_token = NULL;

	if (strcmp(PAREN_L_STR, token) == 0) {
		root = init_arg();
		the_next_token = next_token(input);
		while (strcmp(PAREN_R_STR, the_next_token) != 0) {
			s = parse_expression(the_next_token, input);
			if (s != NULL) {
				enqueue(root->children, s);
			}
			the_next_token = next_token(input);
		}
        if (equal_sym(root->children->tail->element, ELLIPSIS_STR)) {
            root->type = LOOP;
        }
        if (equal_sym(root->children->tail->element, OPTIONAL_STR)) {
            root->type = OPTIONAL;
        }
		if (equal_sym(root->children->head->element, COMMENT_STR)) {
			return NULL;
		}
	}

	return root;
}

Statement *parse_expression(String token, Input *input) {
	if (is_symbol(token)) {
		return init_sym(token);
	} else {
		return parse_statement(token, input);
	}
}

// parse from file //

void eat_whitespace(FILE *in) {
	int c;

	while ((c = getc(in)) != EOF) {
		if (isspace(c)) {
			continue;
		}
		/* comments are whitespace also */
		else if (c == COMMENT) {
			while (((c = getc(in)) != EOF) && (c != '\n'))
				;
			continue;
		}
		ungetc(c, in);
		break;
	}
}

int has_next_statement(FILE *in) {
	Input *input = file_input(in);
	return has_next(input);
}

Statement *next_statement(FILE *in) {
	Input *input = file_input(in);
	String the_next_token = next(input);
	Statement *s = parse_statement(the_next_token, input);
	return s;
}

Statement *read_statement(FILE *in) {
	Statement *s = NULL;
	eat_whitespace(in);
	s = next_statement(in);

	while (empty_statement(s) && fpeek(in) != '\n') {
		s = next_statement(in);
	}
	return s;
}

// parse from string //

Statement *parse(String funny) {
	Input *input = string_input(funny);
	String next_token = NULL;
	next_token = next(input);
	return parse_statement(next_token, input);
}

